#include "threadpool.h"

Threadpool::Threadpool(int num) : threadNum(num), done(false) {
    // std::cout << "Construct entry" << std::endl;
    for (int i = 0; i < threadNum; i++) {
        threads.emplace_back(std::thread(&Threadpool::runTask, this));
    }
}

Threadpool::~Threadpool() {
}

void Threadpool::finish() {
    // std::cout << "Finish entry" << std::endl;

    std::unique_lock<std::mutex> lock(m_mutex);
    done = true;
    lock.unlock();

    for (int i = 0; i < threadNum; i++) {
        // 可能所有线程都在睡眠状态，因此需要唤醒
        m_cond.notify_all();
        // std::cout << "Join thread " << i <<std::endl;
        threads[i].join();
    }
}

void Threadpool::addTask(const Task &t) {
    // std::cout << "addTask entry" << std::endl;

    // 增加任务
    std::unique_lock<std::mutex> lock(m_mutex);
    if (done) {
        // done以后，不允许继续增加任务
        return;
    }
    tasks.push(t);
    // std::cout << "Add a task." << std::endl;
    m_cond.notify_one();
}

void Threadpool::runTask()
{
    while(true) {
        std::unique_lock<std::mutex> lock(m_mutex);

        while (is_empty()) {
            if (done) {
                // 可能其他线程都在wait，唤醒一个
                m_cond.notify_all();
                return;
            }
            // std::cout << "To wait: " << std::this_thread::get_id() << std::endl;
            // 在wait时候会自动释放锁
            m_cond.wait(lock);
        }
        // 被notify以后会自动获得锁

        Task task = std::move(tasks.front());
        tasks.pop();

        lock.unlock();
        // task并行执行
        task();
        // 重新获得锁
        lock.lock();
    }
}

const bool Threadpool::is_empty(void) {
    return tasks.empty();
}
